﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using AVSRadian.Native;

namespace Foasis.Video.AviSynth
{
	/// <summary>
	/// 提供AVS数据相关实例函数
	/// </summary>
	/// <remarks>请配合AvisynthWrapper.dll使用</remarks>
	public class AviSynth : Video
	{

		/// <summary>
		/// AVS文件指针
		/// </summary>
		private IntPtr _avs = IntPtr.Zero;
		/// <summary>
		/// 该AVS文件信息
		/// </summary>
		private AvsInfo _vi;

		/// <summary>
		/// 当前帧类型（关键、空白、一般）
		/// </summary>
		public override FrameType CurrentFrameType
		{
			get
			{
				return FrameType.Key;
			}
		}

		/// <summary>
		/// 该视频尺寸
		/// </summary>
		public override Size Size
		{
			get
			{
				return new System.Drawing.Size(_vi.Width, _vi.Height);
			}
		}

		/// <summary>
		/// 该视频所含帧数
		/// </summary>
		public override int FrameCount
		{
			get
			{
				return _vi.NumberOfFrames;
			}
		}

		/// <summary>
		/// 该视频帧速率
		/// </summary>
		public override double FrameRate
		{
			get
			{
				return (double)_vi.RateN / (double)_vi.RateD;
			}
		}

		/// <summary>
		/// 帧时间点（毫秒）。
		/// </summary>
		public override double[] FrameTime
		{
			get
			{
				return this.frameTime;
			}
		}

		/// <summary>
		/// 得到当前帧数据，byte数组存储。
		/// </summary>
		/// <returns>byte数组，容量必须为视频跨距×视频高度</returns>
		public byte[] GetFrame(int frameIndex)
		{
			int stride = 0;
			switch (_vi.PixelType)
			{
				case AviSynthColorSpace.RGB24:
					stride = _vi.width * 3;
					break;
				case AviSynthColorSpace.RGB32:
					stride = _vi.width * 4;
					break;
				default:
					ThrowAvsExecption();
					break;
			}
			byte[] re = new byte[stride * _vi.Height];
			byte[] tempbits = new byte[stride * _vi.Height];

			NativeMethods.dimzon_avs_getvframe(_avs, tempbits, stride, this.CurrentFrameNumber);

			//返回颜色GBRA（32bits），而Dirext显示需要RGBA（32bits），以下为转换；
			for (int y = 0; y < _vi.Height; y++)
			{
				//RGB存储为上下颠倒，是否颠倒；
				int newy = y;//				_vi.height. - y;
				for (int x = 0; x < stride; x += 4)
				{
					re[x + 2 + stride * newy] = tempbits[(x + 0 + stride * y)];
					re[x + 1 + stride * newy] = tempbits[(x + 1 + stride * y)];
					re[x + 0 + stride * newy] = tempbits[(x + 2 + stride * y)];
					re[x + 3 + stride * newy] = 255;
				}
			}
			return re;
		}

		/// <summary>
		/// 得到当前帧数据，bitmap存储（24bits）。
		/// </summary>
		/// <param name="output">位图信息</param>
		public override void GetFrame(ref Bitmap output, int frameIndex)
		{
			if (output == null || output.PixelFormat != PixelFormat.Format24bppRgb ||
				output.Width != _vi.Width || output.Height != _vi.Height)
			{
				if (output != null)
				{
					output.Dispose();
				}
				output = new Bitmap(_vi.Width, _vi.Height, PixelFormat.Format24bppRgb);
			}
			BitmapData bitmapData = output.LockBits(new System.Drawing.Rectangle(0, 0, output.Width, output.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
			try
			{
				//always bottom-up bitmap
				if (NativeMethods.dimzon_avs_getvframe(_avs, new IntPtr(bitmapData.Scan0.ToInt64() + bitmapData.Stride * (output.Height - 1)), -bitmapData.Stride, frameIndex) != 0)
				{
					ThrowAvsExecption();
				}
			}
			finally
			{
				output.UnlockBits(bitmapData);
			}
		}

		public override void GetFrame(out byte[] outData, int frameIndex, AviSynthColorSpace ColorSpace)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// 打开AVS文件。
		/// </summary>
		/// <param name="filePath">输入文件路径</param>
		public override void Open(string filePath)
		{
			this.Close();
			if (!File.Exists(filePath))
			{
				throw new FileNotFoundException();
			}
			AviSynthColorSpace cs = AviSynthColorSpace.Unknown;
			int sr = new int();
			if (NativeMethods.dimzon_avs_init(ref _avs, "Import", filePath, ref _vi, ref cs, ref sr, this.ColorSpace.ToString()) != 0)
			{
				ThrowAvsExecption();
			}
			else
			{
				this.frameTime = new double[this.FrameCount];
				for (int i = 0; i < this.FrameCount; i++)
				{
					this.frameTime[i] = (double)(i * 1001) / (double)((int)FrameRate + 1);
				}
			}
		}

		/// <summary>
		/// 释放AVS文件
		/// </summary>
		public override void Close()
		{
			if (_avs != IntPtr.Zero)
			{
				NativeMethods.dimzon_avs_destroy(ref _avs);
				_avs = IntPtr.Zero;
			}
		}

		/// <summary>
		/// 抛出AVS错误
		/// </summary>
		private void ThrowAvsExecption()
		{
			StringBuilder sb = new StringBuilder(0x400);
			sb.Length = NativeMethods.dimzon_avs_getlasterror(_avs, sb, 0x400);
			this.Close();
			throw new InvalidDataException("Error AVS Data");
		}

		/// <summary>
		/// 当前帧帧号
		/// </summary>
		public override int CurrentFrameNumber
		{
			get;
			set;
		}

		/// <summary>
		/// 该视频高度
		/// </summary>
		public override int Height
		{
			get
			{
				return _vi.Height;
			}
		}

		/// <summary>
		/// 该视频宽度
		/// </summary>
		public override int Width
		{
			get
			{
				return _vi.Width;
			}
		}

		/// <summary>
		/// 打开avs文件使用的色彩空间。
		/// </summary>
		/// <remarks>默认值为YV12。</remarks>
		public AviSynthColorSpace ColorSpace
		{
			get;
			set;
		}

		/// <summary>
		/// 提供对avs文件的相关操作。
		/// </summary>
		public AviSynth()
		{
			//this.ColorSpace = AviSynthColorspace.YV12;
			this.ColorSpace = AviSynthColorSpace.RGB24;
		}

		/// <summary>
		/// 帧时间点（毫秒）。
		/// </summary>
		private double[] frameTime;

	}
}
